package com.wangzhixuan.commons.intercept;

import java.io.StringReader;
import java.sql.Connection;
import java.util.List;
import java.util.Properties;

import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.wangzhixuan.commons.sqlparser.SelectVisitorImpl;

import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.parser.CCJSqlParserManager;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.select.FromItem;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.SubJoin;
import net.sf.jsqlparser.util.TablesNamesFinder;

@Intercepts({
        @Signature(method = "prepare", type = StatementHandler.class, args = { Connection.class, Integer.class})
})
public class MyBatisInterceptor implements Interceptor {
	   // 控制器本来就是单例，这样似乎更加合理
    protected Logger logger = LogManager.getLogger(getClass());

    private CCJSqlParserManager parserManager = new CCJSqlParserManager();

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        if(invocation.getTarget() instanceof StatementHandler) {
            //逻辑代码区
            StatementHandler statementHandler = (StatementHandler)invocation.getTarget();
            MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);
            // 分离代理对象链(由于目标类可能被多个拦截器拦截，从而形成多次代理，通过下面的两次循环
            // 可以分离出最原始的的目标类)
            while (metaStatementHandler.hasGetter("h")) {
                Object object = metaStatementHandler.getValue("h");
                metaStatementHandler = SystemMetaObject.forObject(object);
            }
            // 分离最后一个代理对象的目标类
            while (metaStatementHandler.hasGetter("target")) {
                Object object = metaStatementHandler.getValue("target");
                metaStatementHandler = SystemMetaObject.forObject(object);
            }
            MappedStatement mappedStatement = (MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement");
            //获取sql
            BoundSql boundSql = statementHandler.getBoundSql();
            String sql = boundSql.getSql();
            //获取方法id
            String id = mappedStatement.getId();

            //获得方法类型
            SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
           if ("queryItems".equals(id)) {
        	   Statement statement = (Statement) CCJSqlParserUtil.parse(sql);
               Select selectStatement = (Select) statement;
               TablesNamesFinder tablesNamesFinder = new TablesNamesFinder();
               List<String> tableList = tablesNamesFinder.getTableList(selectStatement);


               CCJSqlParserManager parserManager = new CCJSqlParserManager();
               Select select = (Select) parserManager.parse(new StringReader(sql));
               PlainSelect plain = (PlainSelect) select.getSelectBody();
               FromItem fromItem = plain.getFromItem();
               processFromItem(fromItem);



               tableList.forEach(tableName -> {
                   System.out.println(tableName);
                   try {
                       Expression where_expression = (Expression) (CCJSqlParserUtil.parseCondExpression(tableName + ".company_id=2"));
                       plain.setWhere(where_expression);

                   } catch (Exception e) {

                   }
               });
               System.out.println(select.toString());
            }

            return invocation.proceed();
        }
        return null;
    }

    @Override
    public Object plugin(Object target) {
        //生成代理对象
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
    }
    
    //循环添加表名
    public static void processFromItem(FromItem fromItem) {
        if (fromItem instanceof SubJoin) {
            SubJoin subJoin = (SubJoin) fromItem;
            if (subJoin.getJoin() != null) {
                if (subJoin.getJoin().getRightItem() != null) {
                    processFromItem(subJoin.getJoin().getRightItem());
                }
            }
            if (subJoin.getLeft() != null) {
                processFromItem(subJoin.getLeft());
            }
            System.out.println(subJoin.getAlias().getName());
        }
    }
}
